#ifndef SOUND_H
#define SOUND_H


#include "timer.h"

#include "samples/lazer.h"
#include "samples/asplode.h"

#include "samples/engine.h"
#include "samples/turret.h"
#include "samples/upgrade.h"

#include "samples/win.h"
#include "samples/menu.h"
#include "samples/gamemusic.h"
#include "samples/loss.h"
//global variables
u16 len = 0;

//////////////////////////////////////////////////
// Programming The Game Boy Advance
// Chapter 9: The Sound System
// SoundTest Project
// main.h header file
//////////////////////////////////////////////////
typedef unsigned char u8;

//define some interrupt registers
#define REG_IME_s *(u16*)0x4000208
#define REG_IE_s *(u16*)0x4000200
#define REG_IF_s *(u16*)0x4000202
#define REG_INTERRUPT_s *(u32*)0x3007FFC
#define REG_DISPSTAT_s *(u16*)0x4000004
#define INT_VBLANK_s 0x0001
//define some DMA registers/values
#define REG_DMA0SAD_s			*(volatile u32*)0x40000B0	//!< DMA 0 Source address
#define REG_DMA0DAD_s			*(volatile u32*)0x40000B4	//!< DMA 0 Destination address
#define REG_DMA0CNT_H_s			*(volatile u32*)0x40000B8	//!< DMA 0 Control

#define REG_DMA1SAD_s *(volatile u32*)0x40000BC
#define REG_DMA1DAD_s *(volatile u32*)0x40000C0
#define REG_DMA1CNT_H_s *(volatile u16*)0x40000C6
    //#define TIMER_ENABLE 0x80
#define DMA_DEST_FIXED_s 64
#define DMA_REPEAT_s 512
#define DMA_32_s 1024
#define DMA_ENABLE_s 32768
#define DMA_TIMING_SYNC_TO_DISPLAY_s 4096 | 8192

//define some sound hardware registers/values
#define REG_SGCNT0_H *(volatile u16*)0x4000082
#define REG_SGCNT1 *(volatile u16*)0x4000084

#define DSA_TIMER0 0x0000
#define DSA_TIMER1 0x0400
#define DSOUND_A_RIGHT_CHANNEL 0x0100
#define DSOUND_A_LEFT_CHANNEL 0x0200
#define DSOUND_A_FIFO_RESET 0x0800

#define DSB_TIMER0 0x0000
#define DSB_TIMER1 0x4000
#define DSOUND_B_RIGHT_CHANNEL 0x01000
#define DSOUND_B_LEFT_CHANNEL 0x02000
#define DSOUND_B_FIFO_RESET 0x08000

#define SOUND_MASTER_ENABLE 128

u16 SamplePosition = 0;
u16 SampleLength = 0;

u16 SamplePosition2 = 0;
u16 SampleLength2 = 0;

char temp[20];

//create a struct to keep track of sound data
typedef struct tagSound
{
	void *pBuffer;
	u16 samplerate;
	u32 length;
	u32 factor;
}sound;

//create variables that describe the sounds
sound s_lazer = {&lazer, 16000, 3600,2};
sound s_enemy_lazer = {&lazer, 8000, 3696,1};
sound s_asplode = {&asplode, 8000, 25296,2};

sound s_turret = {&turret, 16000, 15904,4};
sound s_engine = {&engine, 16000, 43760,4};
sound s_upgrade = {&upgrade, 16000, 19136,4};

sound s_win = {&win, 16000, 648592,4};
sound s_menu = {&menu, 16000, 165664,4};
sound s_game = {&game, 16000, 349456,4};
sound s_loss = {&loss, 16000, 256848,4};


//////////////////////////////////////////////////
// Function: SoundHandler
// Custom interrupt callback function
//////////////////////////////////////////////////
void SoundHandler(void)
{
	u16 Int_Flag;
	//disable interrupts
	REG_IME_s = 0x00;
	//backup the interrupt flags
	Int_Flag = REG_IF_s;
	//look for vertical refresh
	if((REG_IF_s & INT_VBLANK_s) == INT_VBLANK_s)
	{
		//is a sample currently playing?
		// and does it repeat?
		if (SampleLength)		//Does not repeat
		{
			//increment the position, check if complete
			SamplePosition++;
			if (SamplePosition > SampleLength)
			{
				//stop playback: disable the timer and DMA
				REG_TM0CNT = 0;
				REG_DMA1CNT_H_s = 0;
				//reset length
				SampleLength = 0;
			}
		}
	}
	//restore the interrupt flags
	REG_IF_s = Int_Flag;
	//enable interrupts
	REG_IME_s = 0x01;
}

//////////////////////////////////////////////////
// Function: SoundInit
// create interrupt handler
//////////////////////////////////////////////////
void SoundInit(void)
{
    //create custom interrupt handler for vblank (chapter 8)
	REG_IME_s = 0x00;
	REG_INTERRUPT_s = (u32)SoundHandler;
	REG_IE_s |= INT_VBLANK_s;
	REG_DISPSTAT_s |= 0x08;
	REG_IME_s = 0x01;
}

//////////////////////////////////////////////////
// Function: PlaySound
// Plays a sound sample using DMA
// Uses A channels
//////////////////////////////////////////////////
void PlaySound(sound * theSound)
{
	u16 samples;
	//output to both channels and reset the FIFO
	REG_SGCNT0_H = DSOUND_A_RIGHT_CHANNEL | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET;
	//enable all sound
	REG_SGCNT1 = SOUND_MASTER_ENABLE;
	//DMA1 source address
	REG_DMA1SAD_s = (u32)theSound->pBuffer;
	//DMA1 destination address
	REG_DMA1DAD_s = 0x40000A0;
	//write 32 bits into destination every vblank
	REG_DMA1CNT_H_s = DMA_DEST_FIXED_s | DMA_REPEAT_s | DMA_32_s | DMA_TIMING_SYNC_TO_DISPLAY_s | DMA_ENABLE_s;
	//set the sample rate
	samples = 16777216 / theSound->samplerate; 
	REG_TM0D = 65536 - samples;
	//keep track of the playback position and length
	SampleLength = (theSound->length / samples) / theSound->factor * 15.57;
	SamplePosition = 0;
	//enable the timer
	REG_TM0CNT = TIMER_ENABLE;
}


#endif
